#include <ctl_api.h>
#include <targets/LPC2378.h>
#include <targets/liblpc2000.h>

#include "../drivers/rtc.h"

#define ctl_global_interrupts_set(i) libarm_set_irq(i)

static CTL_ISR_FN_t timerCallback;

static unsigned long get_pclk(unsigned long cclk, unsigned long sel)
{
  if (sel == 0)
    return cclk >> 2;
  if (sel == 1)
    return cclk;
  if (sel == 2)
    return cclk >> 1;
  return cclk >> 3;
}

unsigned long get_uart_clk(unsigned long n, unsigned long fosc)
{
  unsigned long pclk = 0;
  unsigned long cclk = liblpc2000_lpc23xx_get_cclk(fosc);
  switch (n)
    {
      case 0:
        pclk = get_pclk(cclk, (PCLKSEL0 & PCLKSEL0_PCLK_UART0_MASK) >> PCLKSEL0_PCLK_UART0_BIT);
        break;
      case 1:
        pclk = get_pclk(cclk, (PCLKSEL0 & PCLKSEL0_PCLK_UART1_MASK) >> PCLKSEL0_PCLK_UART1_BIT);
        break;
      case 2:
        pclk = get_pclk(cclk, (PCLKSEL1 & PCLKSEL1_PCLK_UART2_MASK) >> PCLKSEL1_PCLK_UART2_BIT);
        break;
      case 3:
        pclk = get_pclk(cclk, (PCLKSEL1 & PCLKSEL1_PCLK_UART3_MASK) >> PCLKSEL1_PCLK_UART3_BIT);
        break;
    }
  return pclk;
}

void T0_ISR(void)
{
  timerCallback();
  T0IR = 0xFF; /* Clear the timer 0 interrupt */
  //T0IR = 0x01;
}

void ctl_start_timer(CTL_ISR_FN_t t)
{
  timerCallback = t;
  T0TCR = (1<<T0TCR_Counter_Reset_BIT);; /* Reset timer 0 */
  T0PR = 0; /* Set the timer 0 prescale counter */
  T0MR0 = (get_pclk(liblpc2000_lpc23xx_get_cclk(OSCILLATOR_CLOCK_FREQUENCY), (PCLKSEL0 & PCLKSEL0_PCLK_TIMER0_MASK) >> PCLKSEL0_PCLK_TIMER0_BIT) / 1000) - 1; /* Set timer 0 match register to generate a 1KHz interrupt */
  T0MCR = 3; /* Generate interrupt and reset counter on match */
  T0TCR = (1<<T0TCR_Counter_Enable_BIT);   /* Start timer 0 */  
  
  ctl_set_isr(VICIntSelect_TIMER0_BIT, 1, CTL_ISR_TRIGGER_FIXED, T0_ISR, 0);
  ctl_unmask_isr(VICIntSelect_TIMER0_BIT);
}

unsigned long ctl_get_ticks_per_second(void)
{
  return 1000;
}
